<!--
 * @Author: Jayken
 * @Email: jaykenxie@outlook.com
 * @Date: 2019-08-06 14:03:22
 -->
<template>
  <div class="add-attr">
    <Form :model="attrData" ref="addAttrRef" :label-width="110" :rules="baseRuleValidate">
      <Row :gutter="32" type="flex">
        <Col span="12">
          <Form-item prop="type" :label="$t('module.extend.type')">
            <Select v-model="attrData.type" @on-change="onChangeType">
              >
              <Option v-for="type in typeEmenu" :value="type.val" :key="type.val">{{ type.name }}</Option>
            </Select>
          </Form-item>
        </Col>
        <Col span="12">
          <Form-item prop="field" :label="$t('module.extend.field')">
            <Input
              :placeholder="$t('module.extend.tip.attrname')"
              type="text"
              v-model="attrData.field"
              :maxlength="20"
            />
          </Form-item>
        </Col>
        <Col span="12">
          <Form-item prop="title" :label="$t('module.extend.title')">
            <Input
              type="text"
              :maxlength="10"
              v-model="attrData.title"
              :placeholder="$t('module.extend.tip.attrTitle')"
              @blur.native.capture="onChangeTitle"
            />
          </Form-item>
        </Col>
        <Col span="12">
          <Form-item prop="value" :label="$t('module.extend.value')">
            <Input
              :placeholder="$t('module.extend.tip.enterValue')"
              type="text"
              :maxlength="10"
              v-model="attrData.value"
            />
          </Form-item>
        </Col>
        <!-- 是否必填 -->
        <Col span="12">
          <Form-item :label="$t('module.extend.required')">
            <Select
              :disabled="attrData.type === 'InputNumber'"
              v-model="validate.required"
              @on-change="selectIsRequired"
            >
              <Option v-for="type in typeList" :value="type.val" :key="type.val">{{ type.name }}</Option>
            </Select>
          </Form-item>
        </Col>
        <!-- 验证提示 -->
        <Col span="12">
          <Form-item prop="value" :label="$t('module.extend.valiMsg')">
            <Input
              :disabled="attrData.type === 'InputNumber' || validate.required == 0"
              type="text"
              :maxlength="30"
              v-model="validate.message"
              :placeholder="$t('module.extend.tip.enterValiMsg')"
              @input="changeMessage"
            />
          </Form-item>
        </Col>
        <!-- 选择扩展字段 -->
        <Col span="12">
          <Form-item prop="matchColumn" :label="$t('module.extend.selectExtendAttr')">
            <Select v-model="attrData.matchColumn">
              <Option
                v-for="ext in matchColumnList"
                :value="ext.val"
                :key="ext.val"
                :disabled="ext.disabled"
              >{{ ext.name }}</Option>
            </Select>
          </Form-item>
        </Col>
      </Row>
    </Form>

    <!-- PROPS -->
    <div v-show="ruleData.length > 0">
      <Divider orientation="left">{{ $t("module.extend.props") }}</Divider>
      <form-create v-model="fcApi" :rule="ruleData" :option="option"></form-create>
    </div>

    <!-- options -->
    <div v-show="!isNotLable">
      <Divider orientation="left">{{ $t("module.extend.lable") }}</Divider>
      <div style="padding: 0 20px;">
        <div style="margin-bottom: 10px;">
          <!-- <RPButton icon="md-add" :text="$t('module.extend.addlable')" @click="addOptHandler()" /> -->
          <Button type="error" @click="addOptHandler()">{{ $t("module.extend.addlable") }}</Button>
        </div>
        <Table :columns="addColomns" :data="options"></Table>
      </div>
    </div>
  </div>
</template>
<script>
import locales from "./locales.js";
import propsRules from "./props/index";
import { cloneDeep } from "lodash";
import { optionsColumns } from "./columns";
import addOption from "./addOption";

export default {
  name: "addattr",
  mixins: [locales],
  data: () => ({
    isFreezeMessage: false,
    commonMessage: "",
    attrData: { type: "input", value: "", matchColumn: "" },
    // typeEmenu: [
    //   { name: "输入框", val: "input" },
    //   { name: "数字输入框", val: "InputNumber" },
    //   { name: "单选框", val: "radio" },
    //   { name: "多选框", val: "checkbox" },
    //   { name: "下拉选框", val: "select" }
    // ],
    fcApi: null,
    validate: { required: "0", message: "" },
    fcProps: null,
    mergeFlag: true,
    options: [],
    isModify: false,
    curfield: "",
    matchColumnList: []
  }),
  props: {
    rowData: {
      type: Object,
      default: () => ({})
    },
    isEdit: {
      type: Boolean,
      default: true
    },
    fieldes: {
      type: Array,
      default: () => []
    },
    usedExtList: {
      type: Array,
      default: () => []
    },
    templateCategory: {
      type: String,
      default: '',
      required: true
    }
  },
  computed: {
    typeEmenu() {
      return [
        { name: this.$t("module.extend.input"), val: "input" },
        { name: this.$t("module.extend.numInput"), val: "InputNumber" },
        { name: this.$t("module.extend.radio"), val: "radio" },
        { name: this.$t("module.extend.checkbox"), val: "checkbox" },
        { name: this.$t("module.extend.select"), val: "select" }
      ];
    },
    typeList() {
      return [
        { name: this.$t("module.extend.yes"), val: "1" },
        { name: this.$t("module.extend.no"), val: "0" }
      ];
    },
    addColomns() {
      return optionsColumns.call(this);
    },
    actions() {
      const action = [
        {
          text: this.$t("common.save"),
          theme: "primary",
          handle: () => this.assembly()
        },
        {
          text: this.$t("common.close"),
          handle: () => this.$emit("Close", {})
        }
      ];
      // if (this.isEdit)
      //   action.unshift({
      //     text: this.$t("common.save"),
      //     theme: "warning",
      //     handle: () => this.assembly()
      //   });
      return action;
    },
    option() {
      return {
        resetBtn: false,
        submitBtn: false,
        form: {
          labelWidth: 100,
          size: "default"
        }
      };
    },
    ruleData() {
      const { attrData, mergeFlag, mergeValue } = this;
      const rule = cloneDeep(propsRules[attrData.type]);
      if (attrData.type === "InputNumber") {
        this.validate.required = "0";
        this.validate.message = "";
      }
      if (mergeFlag) mergeValue(rule || []);
      return rule || [];
    },
    baseRuleValidate() {
      const vm = this;
      // 验证属性名
      const validateField = (rule, value = "", callback) => {
        if (value === "") {
          callback(new Error(vm.$t("module.extend.tip.attrname")));
        } else if (this.fieldes.includes(value) && value != this.curfield) {
          callback(new Error(vm.$t("module.extend.tip.nameExist")));
        } else if (value.includes(" ")) {
          callback(new Error(vm.$t("module.extend.tip.noSpace")));
          // 验证属性名不为中文字符
        } else if (/[\u4E00-\u9FA5]/.test(value)) {
          callback(new Error(vm.$t("module.extend.tip.notZh")));
        } else {
          callback();
        }
      };
      let matchColumnRequired = true;
      if (vm?.rowData?.field) {
        // 判读模板是否有扩展字段，有的话必填，旧的模板没有该字段
        matchColumnRequired = 'matchColumn' in vm.rowData;
      }
      return {
        field: [{ required: true, validator: validateField, trigger: "blur" }],
        title: [
          { required: true, message: vm.$t("module.extend.tip.attrTitle"), trigger: "blur" },
          { type: "string", max: 30, message: vm.$t("module.extend.tip.lastLen"), trigger: "blur" }
        ],
        matchColumn: [{ required: matchColumnRequired, message: vm.$t("module.extend.tip.selectExtendAttr"), trigger: "blur" }]
      };
    },
    // 判断当前类型有没有lable
    isNotLable() {
      const { attrData } = this;
      return attrData.type === "input" || attrData.type === "InputNumber";
    }
  },
  watch: {
    rowData: {
      handler(val) {
        // 深克隆变量
        const { id, type, value, field, title, props, options, validate = [], matchColumn = '' } = cloneDeep(val);
        if (type) {
          this.attrData = { type, value, field, title, id, matchColumn };
          this.isModify = true;
          this.curfield = field;
        } else {
          // 如果是新建则添加id
          this.attrData.id = Math.random().toString().substring(2);
        }
        // 判断是否有options
        if (Array.isArray(options)) {
          this.options = options;
        }
        // 获取props
        this.fcProps = this.changeValue(props);
        // 验证
        validate[0] ? (this.validate = this.changeValue(validate[0])) : null;
      },
      immediate: true
    }
  },
  created() {
    this.$emit("SetTitle", this.rowData.id ? this.$t("module.extend.editAttr") : this.$t("module.extend.addAttr"));
    this.$emit("SetPageWidth", 980);
    this.$emit("SetPageActions", this.actions);
    this.commonMessage =
      this.attrData.type == "input" ? this.$t("module.extend.pleaceInput") : this.$t("module.extend.tip.pleaseChoose");

    // 王薪程（2023-12-5）：除了组织只能设置10个，其他都有20个
    // 王薪程（2023-12-7）：员工只放开10个扩展字段，因为员工数据后十个没那么大长度
    const onlyTenExtAtt = ['EMPLOYEE', 'ORG'];
    const extArrLen = onlyTenExtAtt.includes(this.templateCategory) ? 10 : 20;
    this.initMatchColumnList(extArrLen);
  },
  methods: {
    // 如果用户自定义验证提示，验证提示便不会自动生成
    changeMessage(value) {
      if (value) {
        this.isFreezeMessage = true;
      } else {
        this.isFreezeMessage = false;
      }
    },
    // 是否必填
    selectIsRequired(value) {
      if (value == "0") {
        this.validate.message = "";
        this.isFreezeMessage = false;
      } else {
        if (this.attrData.title) {
          this.validate.message = this.commonMessage + this.attrData.title;
        }
      }
    },
    // 修改属性类型
    onChangeType(value) {
      this.commonMessage =
        value == "input" ? this.$t("module.extend.pleaceInput") : this.$t("module.extend.tip.pleaseChoose");
      if (this.validate.required == "1" && !this.isFreezeMessage) {
        this.validate.message = this.commonMessage + this.attrData.title;
      }
    },
    // 修改属性标题
    onChangeTitle() {
      if (this.validate.required == "1" && !this.isFreezeMessage) {
        this.validate.message = this.commonMessage + this.attrData.title;
      }
    },

    // 合并模板值和默认值
    mergeValue(rules) {
      const { fcProps, changeValue } = this;
      if (!fcProps) return;
      this.mergeFlag = false;
      for (const [key, val] of Object.entries(fcProps)) {
        for (const rule of rules) {
          if (key === rule.field) {
            rule.value = val;
          }
        }
      }
    },
    async assembly() {
      const {
        validateForm,
        validateFC,
        fcApi,
        attrData,
        validate,
        changeValue,
        isModify,
        isNotLable,
        options,
        validateType
      } = this;
      try {
        // 调用验证
        await Promise.all([validateForm(), validateFC()]);
        const result = { ...attrData };
        if (!isNotLable) {
          if (options.length === 0) return this.$message.error(this.$t("module.extend.tip.onePlus"));
          result.options = options;
        }
        // 获取props
        const _prop = fcApi.formData() || {};
        if (attrData.type === "InputNumber") {
          _prop.max = _prop.max - 0;
          _prop.min = _prop.min - 0;
          _prop.step = _prop.step - 0;
          result.value = result.value - 0;
        }
        if (_prop.maxlength) {
          _prop.maxlength = _prop.maxlength - 0;
        }
        result.props = changeValue(_prop);
        if (attrData.type === "select") {
          result.props.transfer = true;
        }
        if (validate.required === "1") {
          const { required, message } = validate;
          const valid = {
            required: true,
            // message: message ? commonMessage : commonMessage + attrData.title,
            message: message,
            trigger: validateType(attrData.type, _prop.multiple)
          };
          if (attrData.type === "checkbox") {
            Object.assign(valid, { type: "array", min: 1 });
          }
          result.validate = [valid];
        }
        this.$emit("Close", { result, isModify });
      } catch (error) {
        console.log(error);
      }
    },
    validateType(type, mul) {
      if (type === "input") {
        return "blur";
      } else if (type === "select" && mul) {
        return "array";
      } else {
        return "change";
      }
    },
    validateForm() {
      const { addAttrRef } = this.$refs;
      return new Promise((resolve, reject) => {
        addAttrRef.validate(valid => (valid ? resolve(1) : reject(0)));
      });
    },
    validateFC() {
      const { fcApi, attrData } = this;
      return new Promise((resolve, reject) => {
        if (attrData.type === "checkbox") {
          resolve(1);
        } else {
          fcApi.validate(resolve, reject);
        }
      });
    },
    // 将布尔类型和01互相转换
    changeValue(vals) {
      if (!vals) return null;
      for (const [key, val] of Object.entries(vals)) {
        if (val === "0" || val === "1") {
          vals[key] = val === "1" ? true : false;
        } else if (val === true || val === false) {
          vals[key] = val ? "1" : "0";
        }
      }
      return vals;
    },
    addOptHandler(row = {}) {
      const { options } = this;
      const props = { datas: row, options };
      new this.$pageModal(addOption, { props }, ({ result, isModify }) => {
        if (!result) return;
        if (isModify) {
          for (const opt of options) {
            if (opt.id === result.id) {
              Object.assign(opt, result);
              break;
            }
          }
          return;
        }
        options.push(result);
      });
    },
    optDeleteHandler(row) {
      new $confirm(this.$t("common.warning.confirmToDelete"), this).then(() => {
        this.options = this.options.filter(r => !(row.id === r.id));
      });
    },
    initMatchColumnList(length = 20, prefixStr = 'ext') {
      const { attrData: { matchColumn }, usedExtList } = this
      this.matchColumnList = new Array(length).fill({}).map((_, index) => {
        const val = `${prefixStr}${index + 1}`
        let disabled = usedExtList.includes(val)
        if (matchColumn === val && usedExtList.includes(val)) {
          disabled = false
        }
        return {
          name: val,
          val,
          disabled
        }
      })
    }
  }
};
</script>
<style>
.add-attr .form-create {
  padding: 0;
}
</style>
